package com.eestimate.rest;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.apache.log4j.Logger;

import com.eestimate.exceptions.ErrorCodeEnum;
import com.eestimate.exceptions.ServiceException;
import com.eestimate.services.EmployeeService;
import com.eestimate.services.SupplierService;
import com.eestimate.utils.Constants;
import com.eestimate.utils.FileUploadUtils;
import com.eestimate.utils.PropertiesUtils;
import com.eestimate.valuesobjects.ChemicalVo;
import com.eestimate.valuesobjects.EmployeeVo;
import com.eestimate.valuesobjects.MachineVo;
import com.eestimate.valuesobjects.ToolsConsumablesVo;
import com.eestimate.valuesobjects.containers.BaseContainerVo;
import com.eestimate.valuesobjects.containers.ChemicalContainerVo;
import com.eestimate.valuesobjects.containers.EmployeeContainerVo;
import com.eestimate.valuesobjects.containers.MachineContainerVo;
import com.eestimate.valuesobjects.containers.ToolsConsumablesContainerVo;

public class PublicRestService extends BaseRestService{

	protected final Logger log = Logger.getLogger(PublicRestService.class);
	
	private EmployeeService employeeService;
	
	private SupplierService supplierService;
	
	//private ContractorService contractorService;
	
	@Context
	private HttpHeaders httpHeaders;
	
	@Context
	private Request httpRequest;
	
	@Context
	private ContainerRequestContext requestCtx;
	
	@Context
    private transient HttpServletRequest servletRequest;
	
	@POST
	@Path("/uploadfile")
	@Consumes(MediaType.MULTIPART_FORM_DATA)
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo uploadFile(List<Attachment> attachments) {
		
		BaseContainerVo baseContainerVo = new BaseContainerVo();
		try{
			FileUploadUtils fileUtils = new FileUploadUtils();
			fileUtils.uploadFile(attachments);
			baseContainerVo.meta.code = Constants.SUCCESS;	
		}
		catch(ServiceException exc){
			baseContainerVo.meta.code 		= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			baseContainerVo.meta.error 		= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			baseContainerVo.meta.details 	= ExceptionUtils.getRootCauseMessage(exc).toString();
		}
		return baseContainerVo;
	}

	@POST
	@Path("/register")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo register(@FormParam("companyName") String companyName, @FormParam("companyOverview")	String companyOverview,	@FormParam("companyType") String companyType,	@FormParam("companyWebLink") String companyWebLink,	
									@FormParam("companyLicenseNumber") String companyLicenseNumber, @FormParam("companyLicenseLink") String companyLicenseLink, @FormParam("companyAddress") String companyAddress, @FormParam("companyCountry") String companyCountry,
									@FormParam("employeeFirstName") String employeeFirstName, @FormParam("employeeLastName") String employeeLastName, @FormParam("employeeEmail") String employeeEmail, @FormParam("employeePassword") String employeePassword, @FormParam("employeePhone") String employeePhone) {
		
		EmployeeContainerVo empContainer = new EmployeeContainerVo();
		
		try{
			EmployeeVo empvo 		= new EmployeeVo();
			empvo.firstName				= employeeFirstName;
			empvo.lastName				= employeeLastName;
			empvo.email					= employeeEmail;
			empvo.password				= employeePassword;
			empvo.phone					= employeePhone;
			empvo.company.name 			= companyName;
			empvo.company.overview 		= companyOverview;
			empvo.company.companyType 	= companyType;
			empvo.company.webLink 		= companyWebLink;
			empvo.company.licenseNumber = companyLicenseNumber;
			empvo.company.licenseLink	= PropertiesUtils.getInstance().getProperty(Constants.KEY_FILE_UPLOAD_PATH)+companyLicenseLink;
			empvo.company.address		= companyAddress;
			empvo.company.country 		= companyCountry;
			
			empvo = employeeService.registerAndSendEmail(empvo);
			empContainer.meta.code 			= Constants.SUCCESS;
			empContainer.data 				= empvo;
			return empContainer;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			empContainer.meta.code 		= exc.getErrorCodeEnum().getCode();
			empContainer.meta.error 	= exc.getErrorCodeEnum().getMessage();
			empContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return empContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			empContainer.meta.code 		= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			empContainer.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			empContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return empContainer;
		}
	}
	
	@DELETE
	@Path("/employees/{employeeUuid}")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo deleteEmployeeByUuid(@PathParam("employeeUuid") String uuid){
		BaseContainerVo vo = new BaseContainerVo();
		try{
			employeeService.deleteEmployeeByUuid(uuid);
			vo.meta.code 			= Constants.SUCCESS;
			return vo;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			vo.meta.code 		= exc.getErrorCodeEnum().getCode();
			vo.meta.error 	= exc.getErrorCodeEnum().getMessage();
			vo.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return vo;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			vo.meta.code 		= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			vo.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			vo.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return vo;
		}
	}
	
	@POST
	@Path("/login")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo login(@FormParam("email") String email, @FormParam("password") String password){

		EmployeeContainerVo empContainer = new EmployeeContainerVo();
		
		try{
			EmployeeVo empvo 				= employeeService.login(email,password);
			empContainer.meta.code 			= Constants.SUCCESS;
			empContainer.data 				= empvo;
			return empContainer;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			empContainer.meta.code 		= exc.getErrorCodeEnum().getCode();
			empContainer.meta.error 	= exc.getErrorCodeEnum().getMessage();
			empContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return empContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			empContainer.meta.code 		= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			empContainer.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			empContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return empContainer;
		}
	}
	
	@POST
	@Path("/suppliers/chemicals")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo saveChemical(@FormParam("cleaningService") String cleaningService, @FormParam("cleaningArea") String cleaningArea, @FormParam("application") String application, 
							@FormParam("proposedBrand") String proposedBrand, 	@FormParam("proposedChemical") 	String proposedChemical, 	@FormParam("dilutionRatio") String dilutionRatio, 
							@FormParam("areaCoverage") 	String areaCoverage, 	@FormParam("origin") 			String origin, 				@FormParam("certification") String certification, 
							@FormParam("packing") 		String packing, 		@FormParam("totalAreaCoverage") String totalAreaCoverage, 	@FormParam("companyUuid") String companyUuid){
		
		ChemicalContainerVo chemContainer = new ChemicalContainerVo();
		
		try{
			ChemicalVo chemicalVo 			=  supplierService.saveChemical(cleaningService, cleaningArea, application, proposedBrand, proposedChemical, dilutionRatio, areaCoverage, origin, certification, packing, totalAreaCoverage, companyUuid);
			chemContainer.meta.code 		= Constants.SUCCESS;
			chemContainer.data.add(chemicalVo);
			return chemContainer;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			chemContainer.meta.code 	= exc.getErrorCodeEnum().getCode();
			chemContainer.meta.error 	= exc.getErrorCodeEnum().getMessage();
			chemContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return chemContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			chemContainer.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			chemContainer.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			chemContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return chemContainer;
		}
	}
	
	@GET
	@Path("/suppliers/chemicals/{companyUuid}")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo getChemicalsByCompanyUuid(@PathParam("companyUuid") String companyUuid){
		
		ChemicalContainerVo chemContainer = new ChemicalContainerVo();
		
		try{
			List<ChemicalVo> chemicals	=  supplierService.getChemicalsByCompanyUuid(companyUuid);
			chemContainer.meta.code 		= Constants.SUCCESS;
			chemContainer.data				= chemicals;
			return chemContainer;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			chemContainer.meta.code 	= exc.getErrorCodeEnum().getCode();
			chemContainer.meta.error 	= exc.getErrorCodeEnum().getMessage();
			chemContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return chemContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			chemContainer.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			chemContainer.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			chemContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return chemContainer;
		}
	}
	
	@DELETE
	@Path("/suppliers/chemicals/{uuid}")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo deleteChemicalByUuid(@PathParam("uuid") String uuid){
		
		BaseContainerVo container = new BaseContainerVo();
		
		try{
			supplierService.deleteBusinessObjectByUuid(uuid);
			container.meta.code 		= Constants.SUCCESS;
			return container;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			container.meta.code 	= exc.getErrorCodeEnum().getCode();
			container.meta.error 	= exc.getErrorCodeEnum().getMessage();
			container.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return container;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			container.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			container.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			container.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return container;
		}
	}
	
	@POST
	@Path("/suppliers/machines")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo saveMachine(	@FormParam("application") String application, @FormParam("machineType") String machineType, @FormParam("brand") String brand, 
										@FormParam("model") 	String model, 	@FormParam("origin") 		String origin, 		 @FormParam("fuelType") String fuelType, 
										@FormParam("runTime") 	String runTime, @FormParam("areaCoverage") 	String areaCoverage, @FormParam("capacity") String capacity,
										@FormParam("companyUuid") String companyUuid){
		
		MachineContainerVo machContainer = new MachineContainerVo();
		
		try{
			MachineVo machineVo 			=  supplierService.saveMachine(application, machineType, brand, model, 	origin, fuelType, runTime, areaCoverage, capacity,companyUuid);
			machContainer.meta.code 		= Constants.SUCCESS;
			machContainer.data.add(machineVo);
			return machContainer;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			machContainer.meta.code 	= exc.getErrorCodeEnum().getCode();
			machContainer.meta.error 	= exc.getErrorCodeEnum().getMessage();
			machContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return machContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			machContainer.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			machContainer.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			machContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return machContainer;
		}
	}
	
	@GET
	@Path("/suppliers/machines/{companyUuid}")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo getMachinesByCompanyUuid(@PathParam("companyUuid") String companyUuid){
		
		MachineContainerVo machContainer = new MachineContainerVo();
		
		try{
			List<MachineVo> machines		= supplierService.getMachinesByCompanyUuid(companyUuid);
			machContainer.meta.code 		= Constants.SUCCESS;
			machContainer.data				= machines;
			return machContainer;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			machContainer.meta.code 	= exc.getErrorCodeEnum().getCode();
			machContainer.meta.error 	= exc.getErrorCodeEnum().getMessage();
			machContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return machContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			machContainer.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			machContainer.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			machContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return machContainer;
		}
	}
	
	@DELETE
	@Path("/suppliers/machines/{uuid}")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo deleteMachineByUuid(@PathParam("uuid") String uuid){
		
		BaseContainerVo container = new BaseContainerVo();
		
		try{
			supplierService.deleteBusinessObjectByUuid(uuid);
			container.meta.code 		= Constants.SUCCESS;
			return container;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			container.meta.code 	= exc.getErrorCodeEnum().getCode();
			container.meta.error 	= exc.getErrorCodeEnum().getMessage();
			container.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return container;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			container.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			container.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			container.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return container;
		}
	}
	
	@POST
	@Path("/suppliers/tools")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo saveTools(	@FormParam("application") 	String application, @FormParam("description") 	String description, 
										@FormParam("brand") 		String brand, 		@FormParam("model") 		String model, 		
										@FormParam("origin") 		String origin, 		@FormParam("packing") 	String packing, 
										@FormParam("companyUuid") String companyUuid){
		
		ToolsConsumablesContainerVo container = new ToolsConsumablesContainerVo();
		
		try{
			ToolsConsumablesVo toolVo =  supplierService.saveToolsAndConsumables(application, description, brand, model, origin, packing, companyUuid);
			container.meta.code 		= Constants.SUCCESS;
			container.data.add(toolVo);
			return container;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			container.meta.code 	= exc.getErrorCodeEnum().getCode();
			container.meta.error 	= exc.getErrorCodeEnum().getMessage();
			container.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return container;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			container.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			container.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			container.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return container;
		}
	}
	
	@GET
	@Path("/suppliers/tools/{companyUuid}")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo getToolsByCompanyUuid(@PathParam("companyUuid") String companyUuid){
		
		ToolsConsumablesContainerVo machContainer = new ToolsConsumablesContainerVo();
		
		try{
			List<ToolsConsumablesVo> tools		= supplierService.getToolsAndConsumablesByCompanyUuid(companyUuid);
			machContainer.meta.code 			= Constants.SUCCESS;
			machContainer.data					= tools;
			return machContainer;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			machContainer.meta.code 	= exc.getErrorCodeEnum().getCode();
			machContainer.meta.error 	= exc.getErrorCodeEnum().getMessage();
			machContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return machContainer;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			machContainer.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			machContainer.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			machContainer.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return machContainer;
		}
	}
	
	@DELETE
	@Path("/suppliers/tools/{uuid}")
	@Produces( MediaType.APPLICATION_JSON )
	public BaseContainerVo deleteToolByUuid(@PathParam("uuid") String uuid){
		
		BaseContainerVo container = new BaseContainerVo();
		
		try{
			supplierService.deleteBusinessObjectByUuid(uuid);
			container.meta.code 		= Constants.SUCCESS;
			return container;
		}
		catch(ServiceException exc){
			exc.printStackTrace(System.err);
			container.meta.code 	= exc.getErrorCodeEnum().getCode();
			container.meta.error 	= exc.getErrorCodeEnum().getMessage();
			container.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return container;
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			container.meta.code 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getCode();
			container.meta.error 	= ErrorCodeEnum.INTERNAL_SERVER_ERROR.getMessage();
			container.meta.details	= ExceptionUtils.getRootCauseMessage(exc).toString();
			return container;
		}
	}
	

	
	public String getCompanyTypes() {
		try{
			return PropertiesUtils.getInstance().getProperty(Constants.KEY_COMPANY_TYPES);
		}
		catch(Exception exc){
			exc.printStackTrace(System.err);
			return ExceptionUtils.getRootCauseMessage(exc).toString();
		}
	}

	public void setEmployeeService(EmployeeService employeeService) {
		this.employeeService = employeeService;
	}

	public void setSupplierService(SupplierService supplierService) {
		this.supplierService = supplierService;
	}

//	public void setContractorService(ContractorService contractorService) {
//		this.contractorService = contractorService;
//	}
	
}
